import numpy as np
from tqdm import tqdm

class AdversarialGenerator:
    def __init__(self, model, feature_names, epsilon=0.1):
        self.model = model
        self.feature_names = feature_names
        self.epsilon = epsilon
        
    def fgsm_attack(self, X, y, iterations=5):
        """快速梯度符号攻击"""
        adversarial_samples = X.copy()
        for _ in range(iterations):
            grad = self._compute_gradient(adversarial_samples, y)
            perturbation = self.epsilon * np.sign(grad)
            adversarial_samples = np.clip(adversarial_samples + perturbation, 0, 1)
        return adversarial_samples
    
    def genetic_attack(self, X, y, population_size=50, generations=20):
        """遗传算法攻击"""
        population = self._initialize_population(X, population_size)
        for _ in tqdm(range(generations)):
            fitness = self._calculate_fitness(population, y)
            parents = self._select_parents(population, fitness)
            population = self._crossover(parents)
            population = self._mutate(population)
        return population[np.argmin(self._calculate_fitness(population, y))]
    
    def _compute_gradient(self, X, y):
        """计算模型梯度"""
        X_tensor = tf.convert_to_tensor(X, dtype=tf.float32)
        with tf.GradientTape() as tape:
            tape.watch(X_tensor)
            predictions = self.model(X_tensor)
            loss = tf.keras.losses.binary_crossentropy(y, predictions)
        return tape.gradient(loss, X_tensor).numpy() 